package io.gitee.mingbaobaba.security.core.factory;

import io.gitee.mingbaobaba.security.core.constants.SecurityConstant;
import io.gitee.mingbaobaba.security.core.authority.SecurityAuthorityDefaultImpl;
import io.gitee.mingbaobaba.security.core.authority.SecurityAuthority;
import io.gitee.mingbaobaba.security.core.context.SecurityContext;
import io.gitee.mingbaobaba.security.core.context.SecurityContextDefaultImpl;
import io.gitee.mingbaobaba.security.core.properties.SecurityProperties;
import io.gitee.mingbaobaba.security.core.repository.SecurityCaptchaRepository;
import io.gitee.mingbaobaba.security.core.repository.SecurityCaptchaRepositoryDefaultImpl;
import io.gitee.mingbaobaba.security.core.repository.SecurityRepositoryDefaultImpl;
import io.gitee.mingbaobaba.security.core.repository.SecurityRepository;
import io.gitee.mingbaobaba.security.core.request.SecurityRequest;
import io.gitee.mingbaobaba.security.core.response.SecurityResponse;
import io.gitee.mingbaobaba.security.core.response.SecurityResponseWrapper;
import io.gitee.mingbaobaba.security.core.response.SecurityResponseWrapperDefaultImpl;
import io.gitee.mingbaobaba.security.core.service.SecurityService;
import io.gitee.mingbaobaba.security.core.service.SecurityServiceImpl;
import io.gitee.mingbaobaba.security.core.service.SecurityUserDetailsService;
import io.gitee.mingbaobaba.security.core.service.SecurityUserDetailsServiceDefaultImpl;
import io.gitee.mingbaobaba.security.core.utils.CommonUtil;
import io.gitee.mingbaobaba.security.core.utils.PropertiesUtil;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * <p>认证工厂</p>
 *
 * @author yingsheng.ye
 * @version 1.0.0
 * @since 2023/8/21 22:44
 */
public class SecurityFactory {

    /**
     * 私有化构造方法，此类只允许静态方法调用
     */
    private SecurityFactory() {

    }

    /* **************************************** 配置服务 *************************************** */

    /**
     * 配置信息
     */
    private static final AtomicReference<SecurityProperties> configProperties = new AtomicReference<>();

    /**
     * 配置文件设置
     * <p>
     * 参数 configProperties {@link SecurityProperties}
     */
    public static final Consumer<SecurityProperties> setConfig = (SecurityProperties config) -> {
        SecurityFactory.configProperties.set(config);
        CommonUtil.showBanner();
    };

    /**
     * 获取配置文件
     * <p>
     * 参数 {@link SecurityProperties}
     */
    public static final Supplier<SecurityProperties> getConfig = () -> {
        if (SecurityFactory.configProperties.get() == null) {
            synchronized (SecurityFactory.class) {
                if (SecurityFactory.configProperties.get() == null) {
                    //设置配置文件
                    SecurityFactory.setConfig.accept(SecurityFactory.createConfig.get());
                }
            }
        }
        return SecurityFactory.configProperties.get();
    };

    /**
     * 创建配置文件（非ioc场景下使用）
     * <p>
     * 返回 SecurityProperties
     */
    public static final Supplier<SecurityProperties> createConfig = () ->
            SecurityFactory.createConfigByPath.apply(SecurityConstant.CONFIG_PATH);

    /**
     * 创建配置文件（非ioc场景下使用）
     * <p>
     * 参数 path 文件路径
     * 返回SecurityProperties
     */
    public static final Function<String, SecurityProperties> createConfigByPath = path -> {
        Map<String, String> map = PropertiesUtil.readPropToMap.apply(path);
        return PropertiesUtil.mapToClassObj(map, SecurityProperties.class);
    };

    /* **************************************** 接口服务 *************************************** */

    /**
     * 接口服务
     */
    private static final AtomicReference<SecurityService> securityService = new AtomicReference<>();

    /**
     * 获取接口服务
     * <p>
     * 参数 {@link SecurityService}
     */
    public static final Supplier<SecurityService> getSecurityService = () -> {
        if (SecurityFactory.securityService.get() == null) {
            synchronized (SecurityFactory.class) {
                if (SecurityFactory.securityService.get() == null) {
                    SecurityFactory.setSecurityService.accept(new SecurityServiceImpl());
                }
            }
        }
        return SecurityFactory.securityService.get();
    };

    /**
     * 设置接口服务
     */
    public static final Consumer<SecurityService> setSecurityService = SecurityFactory.securityService::set;

    /* **************************************** 持久化服务接口 *************************************** */

    /**
     * 持久化服务
     */
    private static final AtomicReference<SecurityRepository> securityRepository = new AtomicReference<>();

    /**
     * 获取持久化服务
     * <p>
     * 参数 {@link SecurityRepository}
     */
    public static final Supplier<SecurityRepository> getSecurityRepository = () -> {
        if (SecurityFactory.securityRepository.get() == null) {
            synchronized (SecurityFactory.class) {
                if (SecurityFactory.securityRepository.get() == null) {
                    SecurityFactory.setSecurityRepository.accept(new SecurityRepositoryDefaultImpl());
                }
            }
        }
        return SecurityFactory.securityRepository.get();
    };

    /**
     * 设置持久化服务
     * <p>
     * 参数 repository {@link SecurityRepository}
     */
    public static final Consumer<SecurityRepository> setSecurityRepository = SecurityFactory.securityRepository::set;

    /* **************************************** 请求对象接口 *************************************** */

    /**
     * request对象
     */
    private static final AtomicReference<SecurityRequest> securityRequest = new AtomicReference<>();

    /**
     * 获取request对象
     * <p>
     * 参数 SecurityRequest
     */
    public static final Supplier<SecurityRequest> getSecurityRequest = SecurityFactory.securityRequest::get;


    /**
     * 设置request对象
     * <p>
     * 参数  SecurityRequest
     */
    public static final Consumer<SecurityRequest> setSecurityRequest = SecurityFactory.securityRequest::set;

    /* **************************************** 响应对象接口 *************************************** */

    /**
     * response对象
     */
    private static final AtomicReference<SecurityResponse> securityResponse = new AtomicReference<>();

    /**
     * 获取response对象
     * <p>
     * 参数 SecurityResponse
     */
    public static final Supplier<SecurityResponse> getSecurityResponse = SecurityFactory.securityResponse::get;

    /**
     * 设置response对象
     * <p>
     * 参数  SecurityResponse
     */
    public static final Consumer<SecurityResponse> setSecurityResponse = SecurityFactory.securityResponse::set;

    /* **************************************** 响应包装对象接口 *************************************** */

    /**
     * SecurityResponseWrapper对象
     */
    private static final AtomicReference<SecurityResponseWrapper> securityResponseWrapper = new AtomicReference<>();

    /**
     * 获取SecurityResponseWrapper对象
     * <p>
     * 参数 SecurityResponseWrapper
     */
    public static final Supplier<SecurityResponseWrapper> getSecurityResponseWrapper = () -> {
        if (SecurityFactory.securityResponseWrapper.get() == null) {
            synchronized (SecurityFactory.class) {
                if (SecurityFactory.securityResponseWrapper.get() == null) {
                    SecurityFactory.setSecurityResponseWrapper.accept(new SecurityResponseWrapperDefaultImpl());
                }
            }
        }
        return SecurityFactory.securityResponseWrapper.get();
    };

    /**
     * 设置SecurityResponseWrapper对象
     * <p>
     * 参数  SecurityResponseWrapper
     */
    public static final Consumer<SecurityResponseWrapper> setSecurityResponseWrapper = SecurityFactory.securityResponseWrapper::set;

    /* **************************************** 上下文对象接口 *************************************** */

    /**
     * context上下文对象
     */
    private static final AtomicReference<SecurityContext> securityContext = new AtomicReference<>();

    /**
     * 获取context对象
     * <p>
     * 参数 SecurityContext
     */
    public static final Supplier<SecurityContext> getSecurityContext = () -> {
        if (SecurityFactory.securityContext.get() == null) {
            synchronized (SecurityFactory.class) {
                if (SecurityFactory.securityContext.get() == null) {
                    SecurityFactory.setSecurityContext.accept(new SecurityContextDefaultImpl());
                }
            }
        }
        return SecurityFactory.securityContext.get();
    };

    /**
     * 设置context对象
     * <p>
     * 参数 context SecurityContext
     */
    public static final Consumer<SecurityContext> setSecurityContext = SecurityFactory.securityContext::set;

    /* **************************************** 权限对象接口 *************************************** */
    /**
     * 权限集合对象
     */
    private static final AtomicReference<SecurityAuthority> securityPermission = new AtomicReference<>();

    /**
     * 获取权限集合对象
     * <p>
     * 参数 SecurityPermission
     */
    public static final Supplier<SecurityAuthority> getSecurityPermission = () -> {
        if (SecurityFactory.securityPermission.get() == null) {
            synchronized (SecurityFactory.class) {
                if (SecurityFactory.securityPermission.get() == null) {
                    SecurityFactory.setSecurityPermission.accept(new SecurityAuthorityDefaultImpl());
                }
            }
        }
        return SecurityFactory.securityPermission.get();
    };

    /**
     * 设置权限集合对象
     * <p>
     * 参数 permission SecurityPermission
     */
    public static final Consumer<SecurityAuthority> setSecurityPermission = SecurityFactory.securityPermission::set;

    /* **************************************** 用户明细接口 *************************************** */

    /**
     * 用户明细接口
     */
    private static final AtomicReference<SecurityUserDetailsService> securityUserDetailsService = new AtomicReference<>();

    /**
     * 获取用户明细接口
     * <p>
     * SecurityUserDetailsService
     */
    public static final Supplier<SecurityUserDetailsService> getSecurityUserDetailsService = () -> {
        if (Objects.isNull(SecurityFactory.securityUserDetailsService.get())) {
            synchronized (SecurityFactory.class) {
                if (Objects.isNull(SecurityFactory.securityUserDetailsService.get())) {
                    SecurityFactory.setSecurityUserDetailsService.accept(new SecurityUserDetailsServiceDefaultImpl());
                }
            }
        }
        return SecurityFactory.securityUserDetailsService.get();
    };

    /**
     * 设置用户明细接口
     * <p>
     * SecurityUserDetailsService
     */
    public static final Consumer<SecurityUserDetailsService> setSecurityUserDetailsService = SecurityFactory.securityUserDetailsService::set;

    /* **************************************** 验证码存储接口 *************************************** */
    /**
     * 验证码存储接口
     */
    private static final AtomicReference<SecurityCaptchaRepository> securityCaptchaRepository = new AtomicReference<>();

    /**
     * 获取验证码存储接口
     * <p>
     * SecurityCaptchaRepository
     */
    public static final Supplier<SecurityCaptchaRepository> getSecurityCaptchaRepository = () -> {
        if (Objects.isNull(SecurityFactory.securityCaptchaRepository.get())) {
            synchronized (SecurityFactory.class) {
                if (Objects.isNull(SecurityFactory.securityCaptchaRepository.get())) {
                    SecurityFactory.setSecurityCaptchaRepository.accept(new SecurityCaptchaRepositoryDefaultImpl());
                }
            }
        }
        return SecurityFactory.securityCaptchaRepository.get();
    };

    /**
     * 设置验证码存储接口
     * <p>
     * SecurityCaptchaRepository
     */
    public static final Consumer<SecurityCaptchaRepository> setSecurityCaptchaRepository = SecurityFactory.securityCaptchaRepository::set;

}
